﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using Com.Framework.Enc;
using Com.Framework.Data;

namespace Com.Library.DB.Manager
{
    public class ManagerModel
    {
        private ManagerModel()
        {
        }

        public static int Create(string ManagerID, string ManagerPassword,
            string ManagerName)
        {
			string managerPassHash = GetPassHash(ManagerID, ManagerPassword);

			ManagerCreateArguments arg = new ManagerCreateArguments()
			{
				strManagerID = ManagerID,
				strManagerName = ManagerName,
				strManagerPasshash = managerPassHash
			};

			ManagerCreate access = new ManagerCreate();
			access.SetArguments(arg);
			access.ExecuteNonQuery();

			DataEntity output = access.GetOutput();

			return output.GetData2("n4ManagerSN", 0);
        }

		public static ManagerEntity GetInfo(int? ManagerSN, string ManagerID)
		{
			ManagerGetInfoArguments arg = new ManagerGetInfoArguments();
			if (ManagerSN.HasValue)
			{
				arg.n4ManagerSN = ManagerSN.Value;
				arg.strManagerID = null;
			}
			else
			{
				arg.n4ManagerSN = 0;
				arg.strManagerID = ManagerID;
			}

			ManagerGetInfo access = new ManagerGetInfo();
			access.SetArguments(arg);
			ManagerEntity output = access.ExecuteNonQuery();

			return output;
		}

		public static bool VerifyPassword(string ManagerID, string ManagerPassword)
		{
			ManagerEntity manager = GetInfo(null, ManagerID);

			string hashOnDB = manager.strManagerPasshash;

			string hashOnInput = GetPassHash(ManagerID, ManagerPassword);

			return (hashOnDB == hashOnInput);
		}

		public static void Modify(int ManagerSN, string ManagerPassword, string ManagerName)
		{
			ManagerEntity manager = GetInfo(ManagerSN, null);

			string managerPassHash = null;
			if (!string.IsNullOrEmpty(ManagerPassword))
				managerPassHash = GetPassHash(manager.strManagerID, ManagerPassword);

			ManagerModifyArguments arg = new ManagerModifyArguments()
			{
				n4ManagerSN = ManagerSN,
				strManagerPasshash = managerPassHash,
				strManagerName = string.IsNullOrEmpty(ManagerName)?null:ManagerName
			};

			ManagerModify access = new ManagerModify();
			access.SetArguments(arg);
			access.ExecuteNonQuery();
		}

		public static void ModifyManager(int ManagerSN, byte IsManager)
		{
			ManagerEntity manager = GetInfo(ManagerSN, null);
			ManagerModifyArguments arg = new ManagerModifyArguments()
			{
				n4ManagerSN = ManagerSN,
				IsManager = IsManager
			};

			ManagerModify access = new ManagerModify();
			access.SetArguments(arg);
			access.ExecuteNonQuery();
		}

		public static List<ManagerEntity> GetList(int PageNo, byte PageSize, out int CntRow, out int CntTotal)
		{
			ManagerGetListArguments arg = new ManagerGetListArguments()
			{
				PageNo = PageNo,
				PageSize = PageSize
			};

			ManagerGetList access = new ManagerGetList();
			access.SetArguments(arg);
			access.Execute();

			List<ManagerEntity> list = access.GetRecords();
			DataEntity output = access.GetOutput();

			CntRow = output.GetData2("CntRow", 0);
			CntTotal = output.GetData2("CntTotal", 0);

			return list;
		}

		public static List<ManagerEntity> GetListByManagerID(string ManagerID, int PageNo, byte PageSize, out int CntRow, out int CntTotal)
		{
			ManagerGetListArguments arg = new ManagerGetListArguments()
			{
				strManagerID = ManagerID,
				PageNo = PageNo,
				PageSize = PageSize
			};

			ManagerGetList access = new ManagerGetList();
			access.SetArguments(arg);
			access.Execute();

			List<ManagerEntity> list = access.GetRecords();
			DataEntity output = access.GetOutput();

			CntRow = output.GetData2("CntRow", 0);
			CntTotal = output.GetData2("CntTotal", 0);

			return list;
		}

		public static List<ManagerEntity> GetListByManagerName(string ManagerName, int PageNo, byte PageSize, out int CntRow, out int CntTotal)
		{
			ManagerGetListArguments arg = new ManagerGetListArguments()
			{
				strManagerName = ManagerName,
				PageNo = PageNo,
				PageSize = PageSize
			};

			ManagerGetList access = new ManagerGetList();
			access.SetArguments(arg);
			access.Execute();

			List<ManagerEntity> list = access.GetRecords();
			DataEntity output = access.GetOutput();

			CntRow = output.GetData2("CntRow", 0);
			CntTotal = output.GetData2("CntTotal", 0);

			return list;
		}

		public static void Remove(int ManagerSN)
		{
			ManagerRemoveArguments arg = new ManagerRemoveArguments()
			{
				n4ManagerSN = ManagerSN
			};

			ManagerRemove access = new ManagerRemove();
			access.SetArguments(arg);
			access.Execute();
		}

		private static string GetPassHash(string ManagerID, string ManagerPassword)
		{
			// 패스워드를 해싱하는 방식은 아이디를 sha256으로 해시해서 나온 값을
			// hmac-sha256의 키로 하여 패스워드를 해시하는 방식으로 사용한다.
			// 위쪽 취소. 어차피 hmac 안에서 비슷한 짓을 하므로 키값만 ManagerID로 한다
			// 아이디 패스워드가 둘다 노출되어야 암호가 풀리므로 조금(개미 똥꾸녕정도)
			// 패스워드만 해시 하는것보다 안전함

			HMACSHA256 hasher2 = new HMACSHA256(Encoding.ASCII.GetBytes(ManagerID));
			byte[] passHash = hasher2.ComputeHash(Encoding.ASCII.GetBytes(ManagerPassword));

			string passHashEncoded = ByteArrayEncoder.EncodeHex(passHash);

			return passHashEncoded;
		}
    }
}
